/**
 * 工具，树和节点通用
 *
 */

const Utils = {};

/**
 * 遍历树节点，返回新的树
 * @param datas，树形结构数据
 * @param set，配置
 * @param flatArr，可选，用于构建扁平结构数据的数组
 * @returns {[]}
 */
Utils.creatTree = function(datas, set, flatArr) {

    const newT = [];
    let startId = 1; // 构建树的id，没有找到id字段时，使用该字段

    function visitTree(nodes, parent, newNodes) {

        nodes.forEach(raw => {

            const newNode = creatNode(raw, set);
            newNode.pId = parent ? parent.id : '';
            newNode.id = raw[set.key.id] || ('tid_' + startId++);
            newNode.children = [];

            newNodes.push(newNode);
            Array.isArray(flatArr) && flatArr.push(newNode);

            if (raw.children && raw.children.length) {
                visitTree(raw.children, newNode, newNode.children);
            }
        });
    }
    visitTree(datas || [], null, newT);

    return newT;
};

// 构建新节点数据
function creatNode(item, set) {

    const key = set.key;
    const children = item[key.children] || [];

    // 指定了是否为父节点字段,则使用指定字段，否则根据有无子节点判断
    let isParent = !!children.length;
    if (item.hasOwnProperty(key.isParent)) {
        isParent = item[key.isParent];
    }

    // 是否显示图标
    let showIcon = set.showIcon;
    if (item.hasOwnProperty(key.showIcon)) {
        showIcon = item[key.showIcon];
    }

    return {
        raw: item, // 节点原数据

        name: item[key.name] || '', // 显示名称 String
        title: item[key.title] || '', // tips String
        icon: item[key.icon] || '', // 图标显示字段 String
        showIcon: showIcon, // 是否显示图标字段

        isParent: isParent, // 是否为父节点 Boolean
        isHidden: item[key.isHidden] || false, // 是否隐藏 Boolean
        open: !!item[key.open] || false, // 是否展开，可通过交互改变 Boolean

        checked: item[key.checked] || false, // 是否选中，可通过交互改变 Boolean
        selected: item[key.selected] || false, // 单选是否选中，可通过交互改变 Boolean
        nocheck: item[key.nocheck] || false, // 是否不显示多选框 Boolean
        disabled: item[key.disabled] || false, // 是否禁用节点，禁用后不能多选、单选
    };
}

/**
 * 简单数据转换为树结构
 * @param arr
 * @returns {[]}
 */
Utils.getTreeFromArr = function(arr = []) {
    const tree = [];
    const obj = {};
    let lastArr = [];

    arr.forEach(v => obj[v.id] = {...v, children: []});
    Object.values(obj).forEach(v => {
        if (!obj[v.pId]) {
            tree.push(v);
        } else {
            lastArr.push(v);
        }
    });

    while (lastArr.length) {
        const tmpArr = [];
        lastArr.forEach(v => {
            if (obj[v.pId]) {
                obj[v.pId].children.push(v);
            } else {
                tmpArr.push(v);
            }
        });
        lastArr = tmpArr;
    }

    return tree;
};


export default Utils;
